
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>

#define SERVER_IP "192.168.31.13"
#define SERVER_PORT 50000

int main(int argc, char const *argv[])
{
    int ListenSockFd = socket( AF_INET, SOCK_STREAM, 0 );
    if ( -1 == ListenSockFd )
    {
        perror( "fail socket" );
        return -1;
    }

    int Ret;

    struct sockaddr_in ServerAddr;
    ServerAddr.sin_family      = AF_INET;
    ServerAddr.sin_port        = htons( SERVER_PORT );
    ServerAddr.sin_addr.s_addr = inet_addr( SERVER_IP );
    Ret = bind( ListenSockFd, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr) );
    if ( -1 == Ret )
    {
        perror( "fail socket" );
        return -1;
    }

    Ret = listen( ListenSockFd, 10 );
    if ( -1 == Ret )
    {
        perror( "fail listen" );
        return -1;
    }

    int ConnectSockFd;
    struct sockaddr_in ClintAddr;
    socklen_t ClintAddrLen = sizeof(ClintAddr);

    ConnectSockFd = accept( ListenSockFd, (struct sockaddr*)&ClintAddr, &ClintAddrLen );
    if ( -1 == ConnectSockFd ) 
    {
        perror( "fail accept" );
        return -1;
    }
    printf( "Success connect with %s:%d\n", 
            inet_ntoa( ClintAddr.sin_addr ), ntohs( ClintAddr.sin_port ) );

    
    char RecvBuff[1024] = {0};
    ssize_t RecvSize = 0;
    RecvSize = recv( ConnectSockFd, RecvBuff, sizeof(RecvBuff), 0 );
    printf( "Recv %ld bytes: %s\n", RecvSize, RecvBuff );

    char SendBuff[1024] = {0};
    sprintf( SendBuff, "Echo from %s:%d", SERVER_IP, SERVER_PORT );
    ssize_t SendSize = 0;
    SendSize = send( ConnectSockFd, SendBuff, strlen( SendBuff) + 1, 0 );

    return 0;
}





/*
程序功能
    建立TCP服务器, 并与 TCP客户端 建立连接收发数据.

程序流程
    初始化 TCP服务器
    等待 TCP客户端 连接请求 并建立 连接
    接收 TCP客户端 数据
    发送数据到 TCP客户端
    关闭连接

涉及函数
    socket
    bind
        htons
        inet_addr
    listen
    accept
        inet_ntoa
        ntohs
    recv
    send
    close

知识要点
    TCP服务器的原子操作

测试流程
    02_tcp_clint.c  作为客户端, 设定 TCP服务器的 IP 和 端口 宏定义
    03_tcp_server.c 作为服务器, 设定 TCP服务器的 IP 和 端口 宏定义
    先运行服务器, 再运行客户端

*/